package com.shuaige.paydollarapi.service.impl;

import com.shuaige.paydollarapi.model.CancelOrderResponse;
import com.shuaige.paydollarapi.model.PaydollarQueryResponse;
import com.shuaige.paydollarapi.model.Record;
import com.shuaige.paydollarapi.service.MerchantApiService;
import com.thoughtworks.xstream.XStream;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Objects;

/**
 * @author Administrator
 */
@Service
public class MerchantApiServiceImpl implements MerchantApiService {


    private final OkHttpClient okHttpClient;

    private static final String AND = "&";
    private static final String EQUALS = "=";

    /**
     * 执行动作
     */
    private static final String QUERY = "Query";

    /**
     * API返回字段
     */
    private static final String RESULTCODE = "resultCode";
    private static final String ORDERSTATUS = "orderStatus";
    private static final String REF = "ref";
    private static final String PAYREF = "payRef";
    private static final String AMT = "amt";
    private static final String CUR = "cur";
    private static final String ERRMSG = "errMsg";

    /**
     * url地址
     */
    @Value("${api.query}")
    private String apiQuery;
    @Value("${api.void}")
    private String apivoid;

    /**
     * 固定参数
     */
    @Value("${api.merchantId}")
    private String merchantId;
    @Value("${api.loginId}")
    private String loginId;
    @Value("${api.password}")
    private String password;

    public MerchantApiServiceImpl(OkHttpClient okHttpClient) {
        this.okHttpClient = okHttpClient;
    }

    @Override
    public PaydollarQueryResponse query(String orderRef, String payRef) {
        String url = MessageFormat.format(apiQuery, merchantId,
                loginId,
                password,
                QUERY,
                orderRef,
                payRef);

        System.out.println(url);
        Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            // 设置xml、解析规则
            XStream xstream = new XStream();
            XStream.setupDefaultSecurity(xstream);
            xstream.allowTypes(new Class[]{PaydollarQueryResponse.class, Record.class});
            xstream.alias("records", PaydollarQueryResponse.class);
            xstream.alias("record", Record.class);
            xstream.addImplicitCollection(PaydollarQueryResponse.class, "record");
            // 解析xml
            return (PaydollarQueryResponse) xstream.fromXML(Objects.requireNonNull(response.body()).string());
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public CancelOrderResponse cancelOrder(String payRef, String actionName) {

        String url = MessageFormat.format(apivoid, merchantId,
                loginId,
                password,
                actionName,
                payRef);

        System.out.println(url);
        Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            return getCancellationOfAcceptedPaymentsResponse(
                    Objects.requireNonNull(response.body()).string()
            );
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取请求结果
     *
     * @return
     */
    private CancelOrderResponse getCancellationOfAcceptedPaymentsResponse(String msg) {
        String[] splits = msg.split(AND);
        CancelOrderResponse cancelOrderResponse = new CancelOrderResponse();
        if (StringUtils.isEmpty(splits)) {
            return cancelOrderResponse;
        }
        Arrays.stream(splits)
                .map(s -> s.split(EQUALS))
                .filter(split -> !StringUtils.isEmpty(split) && split.length == 2)
                .forEach(split -> {
                    if (RESULTCODE.equals(split[0])) {
                        cancelOrderResponse.setResultCode(split[1]);
                    }
                    if (ORDERSTATUS.equals(split[0])) {
                        cancelOrderResponse.setOrderStatus(split[1]);
                    }
                    if (REF.equals(split[0])) {
                        cancelOrderResponse.setRef(split[1]);
                    }
                    if (PAYREF.equals(split[0])) {
                        cancelOrderResponse.setPayRef(split[1]);
                    }
                    if (AMT.equals(split[0])) {
                        cancelOrderResponse.setAmt(split[1]);
                    }
                    if (CUR.equals(split[0])) {
                        cancelOrderResponse.setCur(split[1]);
                    }
                    if (ERRMSG.equals(split[0])) {
                        cancelOrderResponse.setErrMsg(split[1]);
                    }
                });
        return cancelOrderResponse;
    }

}
